﻿/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../global/head.h"
#include "../macro/head.h"
#include "../tools/head.h"
#include "../impl/head.h"
#include "protocol_impl.h"

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 

namespace xos_compress
{
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    static protocol_impl::POOL * pool_ptr = 0;

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //

    protocol_impl::protocol_impl()
    {}

    protocol_impl::~protocol_impl()
    {}

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int protocol_impl::get_addr( POOL *** pppPool, LIST *** pppList )
    {
        int ret = 0;
        if( pppPool )
        {
            *pppPool = &pool_ptr;
        }
        if( pppList )
        {
            *pppList = 0;
        }
        return ret;
    }

    int protocol_impl::init()
    {
        int ret = 0;
        return ret;
    }

    int protocol_impl::term()
    {
        int ret = 0;
        return ret;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // 解压
    // 
    int protocol_impl::un_compress( char * lpszDest, int nDestLen, int * lpnDestLen, const char * lpszSrc, int nSrcLen )
    {
        int result = 1;
        int ret = 0;

        i_compress * pCompress = 0;
        xos::xos_u8 u8 = 0;
        enumObjType eType = enumObjType::OBJ_BZIP2;
        bool bCompress = true;
        int nPos = 0;

        if( 0 == ret )
        {
            ret = g_pSysData->m_pContainer->serial()->un_pack_int8( lpszSrc + nPos, &nPos, &nSrcLen, &u8 );
        }

        if( 0 == ret )
        {
            bCompress = 0 != ( u8 & 0x01 );
            if( bCompress )
            {
                eType = ( enumObjType )( u8 >> 1 );
            }
        }

        if( ( 0 == ret ) && !bCompress )
        {
            if( nDestLen >= nSrcLen )
            {
                g_pSysData->m_pContainer->crt()->memcpy( lpszDest, lpszSrc + nPos, nSrcLen );
                result = 0;
            }
            if( lpnDestLen )
            {
                *lpnDestLen = nSrcLen;
            }
            ret = 1;
        }

        if( 0 == ret )
        {
            ret = g_pSysData->m_pMgr->create( eType, ( void ** )&pCompress );
        }

        if( 0 == ret )
        {
            ret = pCompress->un_compress( lpszDest, nDestLen, lpnDestLen, lpszSrc + nPos, nSrcLen );
        }

        if( ( 0 != result ) && ( 0 == ret ) )
        {
            result = 0;
        }

        xos_stl::release_interface( pCompress );

        return result;
    }

    // 
    // 压缩
    // 
    int protocol_impl::compress( char * lpszDest, int nDestLen, int * lpnDestLen, const char * lpszSrc, int nSrcLen, enumObjType eType, bool bLast )
    {
        int result = 1;
        int ret = 0;

        i_compress * pCompress = 0;
        xos::xos_u8 u8 = 0;
        int nPos = 0;

        if( 0 == ret )
        {
            u8 = (int)eType & 0xff;
        }

        if( 0 == ret )
        {
            ret = g_pSysData->m_pContainer->serial()->pack_int8( lpszDest + nPos, nPos, &nPos, &nDestLen, u8 );
        }

        if( ( 0 == ret ) && ( enumObjType::OBJ_NONE == eType ) )
        {
            if( nDestLen >= nSrcLen )
            {
                g_pSysData->m_pContainer->crt()->memcpy( lpszDest, lpszSrc, nSrcLen );
                result = 0;
            }
            if( lpnDestLen )
            {
                *lpnDestLen = nSrcLen;
            }
            ret = 1;
        }

        if( 0 == ret )
        {
            ret = g_pSysData->m_pMgr->create( eType, ( void ** )&pCompress );
        }

        if( 0 == ret )
        {
            ret = pCompress->compress( lpszDest + nPos, nDestLen, lpnDestLen, lpszSrc, nSrcLen, bLast );
        }

        if( ( 0 != result ) && ( 0 == ret ) )
        {
            result = 0;
        }

        if( ( 0 == result ) && lpnDestLen )
        {
            ( *lpnDestLen ) += 1;
        }

        xos_stl::release_interface( pCompress );

        return result;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int protocol_impl::un_compress( xos_box::i_buf * pDestBuf, xos_box::i_buf * pSrcBuf )
    {
        int ret = 0;
        char * lpszDest = pDestBuf->get_data( 0, 0, 0 );
        int nDataLen = pDestBuf->get_len( 0 );
        int nDestBufLen = xos_box::i_buf::BUF_SIZE - nDataLen;
        int nDestLen = 0;
        char * lpszSrc = pSrcBuf->get_data( 0, 0, 0 );
        int nSrcLen = pSrcBuf->get_len( 0 );
        ret = un_compress( lpszDest, nDestBufLen, &nDestLen, lpszSrc, nSrcLen );
        if( 0 == ret )
        {
            pDestBuf->set_len( nDestLen + nDataLen );
        }
        return ret;
    }

    int protocol_impl::compress( xos_box::i_buf * pDestBuf, xos_box::i_buf * pSrcBuf, enumObjType eType, bool bLast )
    {
        int ret = 0;
        char * lpszDest = pDestBuf->get_data( 0, 0, 0 );
        int nDataLen = pDestBuf->get_len( 0 );
        int nDestBufLen = xos_box::i_buf::BUF_SIZE - nDataLen;
        int nDestLen = 0;
        char * lpszSrc = pSrcBuf->get_data( 0, 0, 0 );
        int nSrcLen = pSrcBuf->get_len( 0 );
        ret = compress( lpszDest, nDestBufLen, &nDestLen, lpszSrc, nSrcLen, eType, bLast );
        if( 0 == ret )
        {
            pDestBuf->set_len( nDestLen + nDataLen );
        }
        return ret;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int protocol_impl::un_compress( xos_box::i_list * pDestList, xos_box::i_list * pSrcList )
    {
        int ret = 0;

        xos_box::i_buf * pDest = 0;
        xos_box::i_buf * pSrc = 0;

        while( ( 0 == ret ) && ( pSrc = ( xos_box::i_buf * )pSrcList->front( 0 ) ) )
        {
            pDest = g_pSysData->m_pContainer->buf();
            ret = un_compress( pDest, pSrc );
            if( 0 == ret )
            {
                pDestList->push_back( pDest );
                pSrcList->pop_front();
                pDest = 0;
            }
            else
            {
                pSrc = 0;
            }
            xos_stl::release_interface( pDest );
            xos_stl::release_interface( pSrc );
        }

        return ret;
    }

    int protocol_impl::compress( xos_box::i_list * pDestList, xos_box::i_list * pSrcList, enumObjType eType )
    {
        int ret = 0;

        xos_box::i_buf * pDest = 0;
        xos_box::i_buf * pSrc = 0;

        while( ( 0 == ret ) && ( pSrc = ( xos_box::i_buf * )pSrcList->front( 0 ) ) )
        {
            pDest = g_pSysData->m_pContainer->buf();
            xos_box::i_buf * pEnd = ( xos_box::i_buf * )pSrcList->back( 0 );
            ret = compress( pDest, pSrc, eType, pSrc == pEnd );
            if( 0 == ret )
            {
                pDestList->push_back( pDest );
                pSrcList->pop_front();
                pDest = 0;
            }
            else
            {
                pSrc = 0;
            }
            xos_stl::release_interface( pDest );
            xos_stl::release_interface( pSrc );
        }

        return ret;
    }
}
